Add support for inf -inf and nan
authorJeroen van der Heijden <jeroen@transceptor.technology>
Thu, 14 Jun 2018 15:15:32 +0000 (17:15 +0200)
committerJeroen van der Heijden <jeroen@transceptor.technology>
Thu, 14 Jun 2018 15:15:32 +0000 (17:15 +0200)
grammar/gogrammar/grammar.go
grammar/grammar.py
include/siri/grammar/grammar.h
src/cexpr/cexpr.c
src/siri/db/aggregate.c
src/siri/grammar/grammar.c
test/test_select.py

index b9e12cff145b406b19981b2299376bf52aa18bbf..3f5f2d1ef003fd63096bd348d457caa0f8c3265a 100644 (file)
@@ -4,7 +4,7 @@ package grammar
 // should be used with the goleri module.
 //
 // Source class: SiriGrammar
-// Created at: 2018-05-16 16:15:46
+// Created at: 2018-06-14 16:27:16
 
 import (
        "regexp"
@@ -161,6 +161,7 @@ const (
        GidKIdlePercentage = iota
        GidKIdleTime = iota
        GidKIgnoreThreshold = iota
+       GidKInf = iota
        GidKInfo = iota
        GidKInsert = iota
        GidKInteger = iota
@@ -185,6 +186,8 @@ const (
        GidKMin = iota
        GidKModify = iota
        GidKName = iota
+       GidKNan = iota
+       GidKNinf = iota
        GidKNow = iota
        GidKNumber = iota
        GidKOnline = iota
@@ -365,6 +368,7 @@ func SiriGrammar() *goleri.Grammar {
        )
        kIdlePercentage := goleri.NewKeyword(GidKIdlePercentage, "idle_percentage", false)
        kIdleTime := goleri.NewKeyword(GidKIdleTime, "idle_time", false)
+       kInf := goleri.NewKeyword(GidKInf, "inf", false)
        kInfo := goleri.NewKeyword(GidKInfo, "info", false)
        kIgnoreThreshold := goleri.NewKeyword(GidKIgnoreThreshold, "ignore_threshold", false)
        kInsert := goleri.NewKeyword(GidKInsert, "insert", false)
@@ -394,7 +398,13 @@ func SiriGrammar() *goleri.Grammar {
        kMerge := goleri.NewKeyword(GidKMerge, "merge", false)
        kMin := goleri.NewKeyword(GidKMin, "min", false)
        kModify := goleri.NewKeyword(GidKModify, "modify", false)
+       kNan := goleri.NewKeyword(GidKNan, "nan", false)
        kName := goleri.NewKeyword(GidKName, "name", false)
+       kNinf := goleri.NewSequence(
+               GidKNinf,
+               goleri.NewToken(NoGid, "-"),
+               kInf,
+       )
        kNow := goleri.NewKeyword(GidKNow, "now", false)
        kNumber := goleri.NewKeyword(GidKNumber, "number", false)
        kOnline := goleri.NewKeyword(GidKOnline, "online", false)
@@ -1131,6 +1141,9 @@ func SiriGrammar() *goleri.Grammar {
                        string,
                        rInteger,
                        rFloat,
+                       kNan,
+                       kInf,
+                       kNinf,
                ),
                goleri.NewToken(NoGid, ")"),
        )
index 3ac2da6f191c4b7c98d1733e5869fcb88d59016a..fb96d8d369fdb2ab033a7f44c5d0779d90248611 100644 (file)
@@ -88,6 +88,7 @@ class SiriGrammar(Grammar):
     k_help = Choice(Keyword('help'), Token('?'))
     k_idle_percentage = Keyword('idle_percentage')
     k_idle_time = Keyword('idle_time')
+    k_inf = Keyword('inf')
     k_info = Keyword('info')
     k_ignore_threshold = Keyword('ignore_threshold')
     k_insert = Keyword('insert')
@@ -115,7 +116,9 @@ class SiriGrammar(Grammar):
     k_merge = Keyword('merge')
     k_min = Keyword('min')
     k_modify = Keyword('modify')
+    k_nan = Keyword('nan')
     k_name = Keyword('name')
+    k_ninf = Sequence('-', k_inf)
     k_now = Keyword('now')
     k_number = Keyword('number')
     k_online = Keyword('online')
@@ -343,7 +346,7 @@ class SiriGrammar(Grammar):
             k_buffer_size,
             k_fifo_files,
             k_idle_percentage,
-            k_idle_time,            
+            k_idle_time,
             k_port,
             k_pool,
             k_startup_time,
@@ -494,6 +497,9 @@ class SiriGrammar(Grammar):
             string,
             r_integer,
             r_float,
+            k_nan,
+            k_inf,
+            k_ninf,
             most_greedy=True),
         ')')
     f_limit = Sequence(
@@ -739,7 +745,7 @@ class SiriGrammar(Grammar):
         k_duration_num,
         k_fifo_files,
         k_idle_percentage,
-        k_idle_time,            
+        k_idle_time,
         k_ip_support,
         k_libuv,
         k_list_limit,
index 764dfc2cbc4d69fc75b0c8f26201b1156f00de1f..2875b76c9cc0ea808b3d5ecd397ab5c8f0a2cc3c 100644 (file)
@@ -5,7 +5,7 @@
  * should be used with the libcleri module.
  *
  * Source class: SiriGrammar
- * Created at: 2018-05-16 16:15:46
+ * Created at: 2018-06-14 16:27:16
  */
 #ifndef CLERI_EXPORT_SIRI_GRAMMAR_GRAMMAR_H_
 #define CLERI_EXPORT_SIRI_GRAMMAR_GRAMMAR_H_
@@ -161,6 +161,7 @@ enum cleri_grammar_ids {
     CLERI_GID_K_IDLE_PERCENTAGE,
     CLERI_GID_K_IDLE_TIME,
     CLERI_GID_K_IGNORE_THRESHOLD,
+    CLERI_GID_K_INF,
     CLERI_GID_K_INFO,
     CLERI_GID_K_INSERT,
     CLERI_GID_K_INTEGER,
@@ -185,6 +186,8 @@ enum cleri_grammar_ids {
     CLERI_GID_K_MIN,
     CLERI_GID_K_MODIFY,
     CLERI_GID_K_NAME,
+    CLERI_GID_K_NAN,
+    CLERI_GID_K_NINF,
     CLERI_GID_K_NOW,
     CLERI_GID_K_NUMBER,
     CLERI_GID_K_ONLINE,
index db4542fe92151906fa30c7478d9f41d0cc9d8c51..f706ba08de792521ac5b66807081c57c38a074cb 100644 (file)
@@ -12,6 +12,7 @@
 #include <cexpr/cexpr.h>
 #include <assert.h>
 #include <stddef.h>
+#include <math.h>
 #include <siri/grammar/grammar.h>
 #include <logger/logger.h>
 #include <siri/db/series.h>
@@ -150,17 +151,17 @@ int cexpr_double_cmp(
     switch (operator)
     {
     case CEXPR_EQ:
-        return a == b;
+        return isnan(a) ? isnan(b) : a == b;
     case CEXPR_NE:
-        return a != b;
+        return isnan(a) ? !isnan(b) : a != b;
     case CEXPR_GT:
         return a > b;
     case CEXPR_LT:
         return a < b;
     case CEXPR_GE:
-        return a >= b;
+        return isnan(a) ? isnan(b) : a >= b;
     case CEXPR_LE:
-        return a <= b;
+        return isnan(a) ? isnan(b) : a <= b;
     default:
         log_critical("Got an unexpected operator (int type): %d", operator);
         assert (0);
index 5beda18864b69a064db357cafcb0d6b89451e79c..08c3006990d70a9b2533e1defc13bd24cbfcd477 100644 (file)
@@ -564,6 +564,21 @@ static int AGGREGATE_init_filter(
 {
     switch (node->cl_obj->gid)
     {
+    case CLERI_GID_K_NAN:
+        aggr->filter_tp = TP_DOUBLE;
+        aggr->filter_via.real = NAN;
+        break;
+
+    case CLERI_GID_K_INF:
+        aggr->filter_tp = TP_DOUBLE;
+        aggr->filter_via.real = INFINITY;
+        break;
+
+    case CLERI_GID_K_NINF:
+        aggr->filter_tp = TP_DOUBLE;
+        aggr->filter_via.real = -INFINITY;
+        break;
+
     case CLERI_GID_R_INTEGER:
         aggr->filter_tp = TP_INT;
         aggr->filter_via.int64 = atoll(node->str);
index da6c574b9a3875d13c641dfb26df587c79fb082f..1ab80064194fadb7510b51d1cce7c4649bec47a9 100644 (file)
@@ -5,7 +5,7 @@
  * should be used with the libcleri module.
  *
  * Source class: SiriGrammar
- * Created at: 2018-05-16 16:15:46
+ * Created at: 2018-06-14 16:27:16
  */
 
 #include "siri/grammar/grammar.h"
@@ -79,6 +79,7 @@ cleri_grammar_t * compile_grammar(void)
     );
     cleri_t * k_idle_percentage = cleri_keyword(CLERI_GID_K_IDLE_PERCENTAGE, "idle_percentage", CLERI_CASE_SENSITIVE);
     cleri_t * k_idle_time = cleri_keyword(CLERI_GID_K_IDLE_TIME, "idle_time", CLERI_CASE_SENSITIVE);
+    cleri_t * k_inf = cleri_keyword(CLERI_GID_K_INF, "inf", CLERI_CASE_SENSITIVE);
     cleri_t * k_info = cleri_keyword(CLERI_GID_K_INFO, "info", CLERI_CASE_SENSITIVE);
     cleri_t * k_ignore_threshold = cleri_keyword(CLERI_GID_K_IGNORE_THRESHOLD, "ignore_threshold", CLERI_CASE_SENSITIVE);
     cleri_t * k_insert = cleri_keyword(CLERI_GID_K_INSERT, "insert", CLERI_CASE_SENSITIVE);
@@ -109,7 +110,14 @@ cleri_grammar_t * compile_grammar(void)
     cleri_t * k_merge = cleri_keyword(CLERI_GID_K_MERGE, "merge", CLERI_CASE_SENSITIVE);
     cleri_t * k_min = cleri_keyword(CLERI_GID_K_MIN, "min", CLERI_CASE_SENSITIVE);
     cleri_t * k_modify = cleri_keyword(CLERI_GID_K_MODIFY, "modify", CLERI_CASE_SENSITIVE);
+    cleri_t * k_nan = cleri_keyword(CLERI_GID_K_NAN, "nan", CLERI_CASE_SENSITIVE);
     cleri_t * k_name = cleri_keyword(CLERI_GID_K_NAME, "name", CLERI_CASE_SENSITIVE);
+    cleri_t * k_ninf = cleri_sequence(
+        CLERI_GID_K_NINF,
+        2,
+        cleri_token(CLERI_NONE, "-"),
+        k_inf
+    );
     cleri_t * k_now = cleri_keyword(CLERI_GID_K_NOW, "now", CLERI_CASE_SENSITIVE);
     cleri_t * k_number = cleri_keyword(CLERI_GID_K_NUMBER, "number", CLERI_CASE_SENSITIVE);
     cleri_t * k_online = cleri_keyword(CLERI_GID_K_ONLINE, "online", CLERI_CASE_SENSITIVE);
@@ -946,10 +954,13 @@ cleri_grammar_t * compile_grammar(void)
         cleri_choice(
             CLERI_NONE,
             CLERI_MOST_GREEDY,
-            3,
+            6,
             string,
             r_integer,
-            r_float
+            r_float,
+            k_nan,
+            k_inf,
+            k_ninf
         ),
         cleri_token(CLERI_NONE, ")")
     );
index 994c3afb596d6a5755a8c7459da1e572165a31e8..5cd68392d325ce56f040e119f66791e254021cd6 100644 (file)
@@ -2,6 +2,7 @@ import asyncio
 import functools
 import random
 import time
+import math
 from testing import Client
 from testing import default_test_setup
 from testing import gen_data
@@ -67,6 +68,12 @@ DATA = {
         [1471254712, 'log line two'],
         [1471254714, 'another line (three)'],
         [1471254716, 'and yet one more'],
+    ],
+    'special': [
+        [1471254705, 0.1],
+        [1471254706, math.nan],
+        [1471254707, math.inf],
+        [1471254708, -math.inf],
     ]
 }
 
@@ -80,7 +87,7 @@ class TestSelect(TestBase):
 
         self.assertEqual(
             await self.client0.insert(DATA),
-            {'success_msg': 'Successfully inserted 60 point(s).'})
+            {'success_msg': 'Successfully inserted 64 point(s).'})
 
         self.assertEqual(
             await self.client0.query(
@@ -357,7 +364,8 @@ class TestSelect(TestBase):
                 'Query has reached the maximum number of selected points.*'):
             await self.client0.query(
                 'select * from /.*/')
-        await self.client0.query('alter database set select_points_limit 1000000')
+        await self.client0.query(
+            'alter database set select_points_limit 1000000')
 
         self.client0.close()